﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Security;
using System.Net.Sockets;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Discovery;
using System.ServiceModel.Security;
using System.Text;
using System.Threading;
using VMDS.Business.Processes;
using VMDS.Services.Contracts;
using VMDS.Settings;

namespace VMDS.Services.Hosts
{
    
    public class ManagerServiceHost
    {
        private string p = ServerConfiguration.UpdatePath;
        static string GetFQDN()
        {
            string domainName = IPGlobalProperties.GetIPGlobalProperties().DomainName;
            string hostName = Dns.GetHostName();
            string fqdn = "";
            if (!hostName.Contains(domainName))
                fqdn = hostName + "." + domainName;
            else
                fqdn = hostName;

            return fqdn;
        }



        private ServiceHost sampleServiceHost;
         int FindAvailablePort()
        {
            Mutex mutex = new Mutex(false, "ServiceModelEx.DiscoveryHelper.FindAvailablePort");
            try
            {
                mutex.WaitOne();
                IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, 0);
                using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
                {
                    socket.Bind(endPoint);
                    IPEndPoint local = (IPEndPoint)socket.LocalEndPoint;
                    return local.Port;
                }
            }
            finally
            {
                mutex.ReleaseMutex();
            }
        }
        public void Open()
        {
            #region binding

            var binding = new NetTcpBinding
            {
                CloseTimeout = TimeSpan.FromMinutes(10),
                SendTimeout = TimeSpan.FromMinutes(10),
                OpenTimeout = TimeSpan.FromMinutes(10),
                ReceiveTimeout = TimeSpan.FromMinutes(10),
                MaxBufferPoolSize = 2147483647,
                MaxReceivedMessageSize = 2147483647,
                Security =
                {

                    Mode = SecurityMode.Message,
                    Message = new MessageSecurityOverTcp()
                                  {
                                      ClientCredentialType = MessageCredentialType.Windows
                                  }
                    /*Mode = SecurityMode.Transport,
                    Message = new MessageSecurityOverTcp()
                    {
                        AlgorithmSuite = SecurityAlgorithmSuite.Basic256,
                        ClientCredentialType = MessageCredentialType.Windows
                    },
                    Transport = new TcpTransportSecurity()
                    {
                        ProtectionLevel = ProtectionLevel.EncryptAndSign,
                        ClientCredentialType = TcpClientCredentialType.Windows
                    }*/
                },MaxConnections = 10000,MaxBufferSize = int.MaxValue


            };

            var bindingmex = new NetTcpBinding
            {
                CloseTimeout = TimeSpan.FromMinutes(10),
                SendTimeout = TimeSpan.FromMinutes(10),
                OpenTimeout = TimeSpan.FromMinutes(10),
                ReceiveTimeout = TimeSpan.FromMinutes(10),
                MaxBufferPoolSize = 2147483647,
                MaxReceivedMessageSize = 2147483647,
                Security = { Mode = SecurityMode.None },MaxBufferSize = int.MaxValue
            };
            binding.ReaderQuotas.MaxArrayLength = int.MaxValue;
            bindingmex.ReaderQuotas.MaxArrayLength = int.MaxValue;
            binding.ReaderQuotas.MaxBytesPerRead = int.MaxValue;
            bindingmex.ReaderQuotas.MaxBytesPerRead = int.MaxValue;

            #endregion


            sampleServiceHost = new ServiceHost(typeof(MainService.MainService));

            sampleServiceHost.Description.Behaviors.Clear();
            var behaviour = new ServiceBehaviorAttribute
            {
                InstanceContextMode = InstanceContextMode.PerCall,
                ConcurrencyMode = ConcurrencyMode.Multiple,
                MaxItemsInObjectGraph = 2147483647, AutomaticSessionShutdown = true
            };
            sampleServiceHost.Description.Behaviors.Add(behaviour);

            var throttling = new ServiceThrottlingBehavior()
                                 {
                                     MaxConcurrentCalls = 10000,
                                     MaxConcurrentSessions = 10000,
                                     MaxConcurrentInstances = 10000
                                 };
            sampleServiceHost.Description.Behaviors.Add(throttling);

            var serviceMetadataBehavior = new ServiceMetadataBehavior { HttpGetEnabled = false };
            sampleServiceHost.Description.Behaviors.Add(serviceMetadataBehavior);

            var serviceDebugBehavior = new ServiceDebugBehavior
            {
                HttpHelpPageEnabled = true,
                HttpsHelpPageEnabled = true,
                IncludeExceptionDetailInFaults = true
            };
            sampleServiceHost.Description.Behaviors.Add(serviceDebugBehavior);

            /*  var auditBehavior = new ServiceSecurityAuditBehavior()
                                    {
                                        AuditLogLocation = AuditLogLocation.Application,
                                        MessageAuthenticationAuditLevel = AuditLevel.SuccessOrFailure,
                                        ServiceAuthorizationAuditLevel = AuditLevel.SuccessOrFailure,
                                        SuppressAuditFailure = true
                                    };
                sampleServiceHost.Description.Behaviors.Add(auditBehavior);*/


            //  listening end point 
    
            sampleServiceHost.Credentials.WindowsAuthentication.IncludeWindowsGroups = true;
            
            sampleServiceHost.Credentials.WindowsAuthentication.AllowAnonymousLogons = true;
            

            string addr = "net.tcp://"+GetFQDN()+":1234/vmds";
            string mex = "net.tcp://" + GetFQDN() + ":1235/vmds/mex";
            sampleServiceHost.AddServiceEndpoint(typeof(IMainServiceContract), binding, addr);
            sampleServiceHost.AddServiceEndpoint(typeof(IMetadataExchange), bindingmex, mex);
           
            //  and mex endpoint  
            sampleServiceHost.Description.Behaviors.Add(new ServiceDiscoveryBehavior());
            sampleServiceHost.AddServiceEndpoint(new UdpDiscoveryEndpoint());

            sampleServiceHost.Authorization.ImpersonateCallerForAllOperations = false;
           
            sampleServiceHost.Open();
        }
    }
     
}
